package com.spzx.cart.service.impl;

import com.spzx.cart.api.domain.CartInfo;
import com.spzx.cart.service.ICartService;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.context.SecurityContextHolder;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.product.api.RemoteProductService;
import com.spzx.product.api.domain.ProductSku;
import com.spzx.product.api.domain.vo.SkuPrice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CartServiceImpl implements ICartService {

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    RemoteProductService remoteProductService;


    @Override
    public void addToCart(Long skuId, Integer skuNum) {
        //获取用户id
        Long userId = SecurityContextHolder.getUserId();
        //大key
        String cartKey = getCartKey(userId);

        //小key
        String hashKey = skuId.toString();

        BoundHashOperations<String, String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);

        if (boundHashOperations.hasKey(hashKey)) { //再次
            CartInfo cartInfo = boundHashOperations.get(hashKey);
            int total = cartInfo.getSkuNum() + skuNum;
            int threshold = 99; //单品不能超过99
            cartInfo.setSkuNum(total > threshold ? threshold : total);
            cartInfo.setUpdateTime(new Date());
            boundHashOperations.put(hashKey, cartInfo);
        } else { //首次

            Long size = boundHashOperations.size();
            if (++size > 50) {
                throw new ServiceException("商品数量不能超过50件.");
            }

            CartInfo cartInfo = new CartInfo();

            cartInfo.setCreateTime(new Date());
            cartInfo.setUpdateTime(new Date());

            cartInfo.setUserId(userId);
            cartInfo.setSkuId(skuId);

            R<ProductSku> productSkuResult = remoteProductService.getProductSku(skuId, SecurityConstants.INNER);
            if (productSkuResult.getCode() == R.FAIL) {
                throw new ServiceException(productSkuResult.getMsg());
            }
            ProductSku productSku = productSkuResult.getData();

            cartInfo.setCartPrice(productSku.getSalePrice()); //第一次添加这个商品的当时价格
            cartInfo.setSkuPrice(productSku.getSalePrice()); //商品实时价格

            cartInfo.setSkuNum(1); //首次添加商品默认购买数量就是1
            cartInfo.setThumbImg(productSku.getThumbImg()); //缩略图
            cartInfo.setSkuName(productSku.getSkuName());
            //cartInfo.setIsChecked(1); //默认勾选
            boundHashOperations.put(hashKey, cartInfo);
        }

    }

    /**
     * 获取购物车key
     *
     * @param userId
     * @return
     */
    private static String getCartKey(Long userId) {
        return "user:cart:" + userId;
    }

    @Override
    public List<CartInfo> cartList() {
        //获取用户id
        Long userId = SecurityContextHolder.getUserId();
        //大key
        String cartKey = getCartKey(userId);

        BoundHashOperations<String, String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = boundHashOperations.values();
        if (CollectionUtils.isEmpty(cartInfoList)) {
            return new ArrayList<>();
        }

        //1.排序 根据创建时间倒序
        List<CartInfo> sortedCartInfoList = cartInfoList.stream()
                .sorted((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime())).toList();

        //2.调用远程获取商品的最新价格。 采用批量方式获取，提高效率。
        List<Long> skuIdList = sortedCartInfoList.stream().map(CartInfo::getSkuId).toList();
        R<List<SkuPrice>> skuPriceListResult = remoteProductService.getSkuPriceList(skuIdList, SecurityConstants.INNER);
        if (skuPriceListResult.getCode() == R.FAIL) {
            throw new ServiceException(skuPriceListResult.getMsg());
        }
        List<SkuPrice> skuPriceList = skuPriceListResult.getData();
        Map<Long, BigDecimal> skuIdToSalePriceMap = skuPriceList.stream()
                .collect(Collectors.toMap(SkuPrice::getSkuId, SkuPrice::getSalePrice));

        for (CartInfo cartInfo : sortedCartInfoList) {
            //更新实时价格。更新的是JVM内存中的Bean的属性值；不是Redis中CartInfo对象的属性值(redis数据没变  没变 没变)。
            cartInfo.setSkuPrice(skuIdToSalePriceMap.get(cartInfo.getSkuId()));
        }

        return sortedCartInfoList;
    }

    @Override
    public void deleteCart(Long skuId) {
        //获取用户id
        Long userId = SecurityContextHolder.getUserId();
        //大key
        String cartKey = getCartKey(userId);

        //小key
        String hashKey = skuId.toString();

        BoundHashOperations<String, String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);

        if (boundHashOperations.hasKey(hashKey)) {
            boundHashOperations.delete(hashKey);
        }
    }

    @Override
    public void checkCart(Long skuId, Integer isChecked) {
        //获取用户id
        Long userId = SecurityContextHolder.getUserId();
        //大key
        String cartKey = getCartKey(userId);

        //小key
        String hashKey = skuId.toString();

        BoundHashOperations<String, String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);

        if (boundHashOperations.hasKey(hashKey)) {
            CartInfo cartInfo = boundHashOperations.get(hashKey);
            cartInfo.setIsChecked(isChecked);
            boundHashOperations.put(hashKey, cartInfo);
        }
    }

    @Override
    public void allCheckCart(Integer isChecked) {
        //获取用户id
        Long userId = SecurityContextHolder.getUserId();
        //大key
        String cartKey = getCartKey(userId);

        BoundHashOperations<String, String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);

        List<CartInfo> cartInfoList = boundHashOperations.values();

        if (!CollectionUtils.isEmpty(cartInfoList)) {
            for (CartInfo cartInfo : cartInfoList) {
                cartInfo.setIsChecked(isChecked);
                boundHashOperations.put(cartInfo.getSkuId().toString(), cartInfo);
            }
        }
    }

    @Override
    public void clearCart() {
        //获取用户id
        Long userId = SecurityContextHolder.getUserId();
        //大key
        String cartKey = getCartKey(userId);

        if (redisTemplate.hasKey(cartKey)) {
            redisTemplate.delete(cartKey);
        }
    }


    @Override
    public List<CartInfo> getCartCheckedList(Long userId) {
        //大key
        String cartKey = getCartKey(userId);

        BoundHashOperations<String, String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);

        List<CartInfo> cartInfoList = boundHashOperations.values();

        List<CartInfo> checkedCartInfoList = new ArrayList<>();

        for (CartInfo cartInfo : cartInfoList) {
            if (cartInfo.getIsChecked().intValue() == 1) {
                checkedCartInfoList.add(cartInfo);
            }
        }

        return checkedCartInfoList;
    }

    @Override
    public Boolean updateCartPrice(Long userId) {
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOperations = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartCachInfoList = hashOperations.values();
        List<CartInfo> cartInfoCheckedList = cartCachInfoList.stream().filter((cartInfo) -> cartInfo.getIsChecked() == 1).toList();

        List<Long> skuIdCheckedList = cartInfoCheckedList.stream().map(CartInfo::getSkuId).toList();

        R<List<SkuPrice>> skuPriceListResult = remoteProductService.getSkuPriceList(skuIdCheckedList, SecurityConstants.INNER);

        if (skuPriceListResult.getCode() == R.FAIL) {
            throw new ServiceException(skuPriceListResult.getMsg());
        }

        List<SkuPrice> skuPriceCheckedList = skuPriceListResult.getData(); //数据库最新商品价格
        //将List转Map方便获取数据
        Map<Long, BigDecimal> skuIdToSalePriceMap = skuPriceCheckedList.stream()
                .collect(Collectors.toMap(SkuPrice::getSkuId, SkuPrice::getSalePrice));

        for (CartInfo cartInfo : cartInfoCheckedList) {
            cartInfo.setCartPrice(skuIdToSalePriceMap.get(cartInfo.getSkuId()));
            cartInfo.setSkuPrice(skuIdToSalePriceMap.get(cartInfo.getSkuId()));
            hashOperations.put(cartInfo.getSkuId().toString(),cartInfo);
        }

        return true;
    }

    /*
    //不允许在循环中远程调用，不允许循环调用业务层、Mapper ； 都会影响性能。
    @Override
    public Boolean updateCartPrice(Long userId) {
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOperations = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartCachInfoList = hashOperations.values();
        if (!CollectionUtils.isEmpty(cartCachInfoList)) {
            for (CartInfo cartInfo : cartCachInfoList) {
                if (cartInfo.getIsChecked().intValue() == 1) {
                    SkuPrice skuPrice = remoteProductService.getSkuPrice(cartInfo.getSkuId(), SecurityConstants.INNER).getData();
                    cartInfo.setCartPrice(skuPrice.getSalePrice());
                    cartInfo.setSkuPrice(skuPrice.getSalePrice());
                    hashOperations.put(cartInfo.getSkuId().toString(), cartInfo);
                }
            }
        }
        return true;
    }*/


    @Override
    public Boolean deleteCartCheckedList(Long userId) {
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOperations = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartCachInfoList = hashOperations.values();
        if(!CollectionUtils.isEmpty(cartCachInfoList)){
            for (CartInfo cartInfo : cartCachInfoList) {
                if(cartInfo.getIsChecked() == 1){
                    hashOperations.delete(cartInfo.getSkuId().toString());
                }
            }
        }
        return true;
    }
}